//
//  LAURefreshControl.swift
//  SwiftWeibo
//
//  Created by Lausen on 2017/5/4.
//  Copyright © 2017年 id. All rights reserved.
//

import UIKit

/// 俯视图拖拽的高度
private let refreshHeight: CGFloat = 126

/// 刷新状态的枚举
///
/// - refreshStateNormal: label的text 为 下拉刷新
/// - refreshStatePulling: label的text 为 松开刷新
/// - refreshStateWillRefresh: lable的text 为 正在刷新
enum LAURefreshState {
    case refreshStateNormal
    case refreshStatePulling
    case refreshStateWillRefresh
}

class LAURefreshControl: UIControl {
    
    private weak var scrollView: UIScrollView?
    
    /// 懒加载刷新视图
    fileprivate lazy var refreshView: LAURefreshView = LAURefreshView.refreshView()
    
    init() {
        super.init(frame: CGRect())
        setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        setupUI()
    }
    
    override func willMove(toSuperview newSuperview: UIView?) {
        super.willMove(toSuperview: newSuperview)
        
        guard let sv = newSuperview as? UIScrollView else {
            
            return
        }
        
        scrollView = sv
        
        // 设置scrollView的偏移量
        scrollView?.contentInset = UIEdgeInsets(top: 64, left: 0, bottom: 0, right: 0)
        
        ///KVO添加监听
        scrollView?.addObserver(self, forKeyPath: "contentOffset", options: [], context: nil)
    }
    
    // 本视图从父视图上移除
    //提示:所有的下拉刷新框架都是监听父视图的contentOffset
    //所有的框架的KVO监听实现思路都是这个
    override func removeFromSuperview() {
        
        //:在这里superView还在
        superview?.removeObserver(self, forKeyPath: "contentOffset")
        
        super.removeFromSuperview()
        
        //:在这里superView不在了
    }
    
    ///所有的kvo都会统一调用这个方法,
    //在程序中,通常只监听某一个对象的某几个属性,如果属性太多,方法就会很乱!
    //观察者模式,在不需要的时候,都需要释放
    //1:通知中心:如果不释放,什么也不会发生,但是会有内存泄露,会有多次注册的可能
    //2:KVO:如果不释放,会崩溃
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        guard let scrollView = scrollView else {
            
            return
        }
        
        let height = -(scrollView.contentInset.top + scrollView.contentOffset.y)
    
        frame = CGRect(x: 0,
                       y: -height,
                       width: scrollView.bounds.width,
                       height: height)
        
        /// 给刷新视图的高度赋值
        refreshView.parentViewHeight = height
        
        /// 避免向上滑动的时候,还是会出现刷新空间
        if height < 0 {
            
            return
        }
        
        if scrollView.isDragging {
            
            if height > refreshHeight && (refreshView.refreshState == .refreshStateNormal){
                
                refreshView.refreshState = .refreshStatePulling
                
                print("再使劲")
                
            }else if height < refreshHeight && (refreshView.refreshState == .refreshStatePulling) {
                
                print("松手不刷新")
                
                refreshView.refreshState = .refreshStateNormal
            }
            
        }else{
            
            if refreshView.refreshState == .refreshStatePulling {
                
                print("开始刷新")
                
                /// 整合了KVO的拖拽刷新和直接调用方法的刷新
                beginRefreshing()
                
                /// 发送事件
                sendActions(for: .valueChanged)
            }
        }
    }
    
    /// 开始刷新
    func beginRefreshing(){
        
        print("开始刷新")
        
        guard let scrollView = scrollView else {
            
            return
        }
        
        if refreshView.refreshState == .refreshStateWillRefresh {
            
            return
        }
        
        refreshView.parentViewHeight = refreshHeight
        
        refreshView.refreshState = .refreshStateWillRefresh
        
        var inset = scrollView.contentInset
        
        inset.top += refreshHeight
        scrollView.contentInset = inset
    }
    
  
    /// 结束刷新
    func endRefreshing(){
        
        guard let scrollView = scrollView else {
            
            return
        }
        
        /// 做一个刷新状态的判断,如果不是正正在刷新,就直接返回
        if refreshView.refreshState != .refreshStateWillRefresh {
            
            return
        }
        
        //1:恢复状态
        refreshView.refreshState = .refreshStateNormal
        
        //2:设置superView的contentInset
        var inset = scrollView.contentInset
        inset.top -= refreshHeight
        scrollView.contentInset = inset
    }
}


extension LAURefreshControl{
    
    fileprivate func setupUI(){
        
        backgroundColor = superview?.backgroundColor
        
        /// 裁剪多出空间的部分
//        clipsToBounds = true
        
        /// 添加刷新空间
        addSubview(refreshView)
        
        /// 设置约束
        refreshView.translatesAutoresizingMaskIntoConstraints = false
        
        addConstraint(NSLayoutConstraint(item: refreshView,
                                         attribute: .centerX,
                                         relatedBy: .equal,
                                         toItem: self,
                                         attribute: .centerX,
                                         multiplier: 1.0,
                                         constant: 0))
        
        addConstraint(NSLayoutConstraint(item: refreshView,
                                         attribute: .bottom,
                                         relatedBy: .equal,
                                         toItem: self,
                                         attribute: .bottom,
                                         multiplier: 1.0,
                                         constant: 0))
        
        addConstraint(NSLayoutConstraint(item: refreshView,
                                         attribute: .width,
                                         relatedBy: .equal,
                                         toItem: nil,
                                         attribute: .notAnAttribute,
                                         multiplier: 1.0,
                                         constant: refreshView.bounds.width))
        addConstraint(NSLayoutConstraint(item: refreshView,
                                         attribute: .height,
                                         relatedBy: .equal,
                                         toItem: nil,
                                         attribute: .notAnAttribute,
                                         multiplier: 1.0,
                                         constant: refreshView.bounds.height))
        
    }
}







